package main

import (
	"fmt"
)

func main() {
	/*
			map：映射，是一种专门用于存储赋值对象的集合，属于引用类型，长度是不固定的

			存储特点：
				A：存储的是无序的键值对

				B：键不能重复，并且和 value 值一一对应
					map 中的 key 不能重复，如果重复，那么新的 value 会覆盖原来的，程序不会报错

			语法结构：
				1.创建 map
					var map1 map[key类型]value类型
						nil map，无法直接使用
					var map2 = make(map[key类型]value类型)
		  				key类型：任意可比较的类型，value类型：值类型

					var map2 = map[key类型]value类型{key:value,key:value,key:value...}

				2.添加/修改
					map[key] = value
						如果 key 存在，就是修改数据
						如果 key 不存在，就是添加数据

				3.获取
					map[key] --> value

					//更友好的方法
					value,ok := map[key]
						根据 key 获取相应的 value
							如果 key 存在，value 就是对应的数据，ok 为 true
							如果 key 不存在，value 就是值类型的默认值，ok 为 false

				4.删除数据
					delete(map, key)
						如果 key 存在，就可以直接删除
						如果 key 不存在，删除失败，map 不受影响

				5.长度
					len()

				6.清空
					go语言没有为 map 提供任何清空所有元素的办法，清空 map 的唯一办法是：
						重新 make 一个新的 map
						map1 = make(map[string]string) //清空 map1
					（不用担心垃圾回收的效率，go语言的垃圾回收比写一个清空函数更高效）

				7.不能通过 map 引用，直接修改 mapValue 内的某个元素的值，必须整体赋值
					eg： map[1].a = newA (不可行)


			每种数据类型：
				int: 0
				float: 0.0 ——> 0
				string:""
				array:[0 0 0 0]

				slice: nil // 可以直接使用
				map: nil // 不可以直接使用
	*/
	//1.创建 map
	var map1 map[int]string                                       // 没有初始化，nil（连盘子都没有）
	var map2 = make(map[int]string)                               // 创建（有盘子，没东西）
	var map3 = map[string]int{"Go": 98, "Python": 79, "Html": 93} // 既有盘子，也有东西
	fmt.Println(map1)                                             // map[]
	fmt.Println(map2)                                             // map[]
	fmt.Println(map3)                                             // map[Go:98 Html:93 Python:79]

	fmt.Println(map1 == nil) // true
	fmt.Println(map2 == nil) // false
	fmt.Println(map3 == nil) // false

	//2.nil map
	//map1[1] = "hello" // assignment to entry in nil map
	if map1 == nil {
		map1 = make(map[int]string)
		fmt.Println(map1 == nil) // false
	}

	//存储键值对到 map
	//map1[key] = value
	map1[1] = "hello"
	map1[2] = "world"
	map1[3] = "memeda"
	map1[4] = "www"
	map1[5] = ""

	//4.获取数据，根据 key 获取对应的 value 值
	//根据 key 获取对应的 value 值，如果 key 存在，获取数值，如果 key 不存在，获取的是 value 值类型的零值
	fmt.Println(map1)
	fmt.Println(map1[4])  //根据 key 为 4，获取对应的 value 值
	fmt.Println(map1[40]) // ""

	v1, ok := map1[40] // 判断键值 key 是否存在
	if ok {
		fmt.Println("对应的数值是：", v1)
	} else {
		fmt.Println("操作的 key 不存在，获取到的是零值：", v1)
	}

	//5.修改键值
	fmt.Println(map1) //map[1:hello 2:world 3:memeda 4:www 5:]
	map1[3] = "如花"
	fmt.Println(map1) //map[1:hello 2:world 3:如花 4:www 5:]

	//6.删除数据
	//在执行删除操作时，是根据键值来删除的，如果键值存在，则删除该元素，如果不存在，则 map 不受影响
	delete(map1, 3)
	fmt.Println(map1) // map[1:hello 2:world 4:www 5:]
	delete(map1, 30)
	fmt.Println(map1) // map[1:hello 2:world 4:www 5:]

	//7.长度
	fmt.Println(len(map1)) // 4

	//8.
	map0 := make(map[int]User)
	ander := User{
		name: "喜羊羊",
		age:  18,
	}
	map0[1] = ander

	//错误的修改方法：
	//map0[1].name = "灰太狼" //不可行

	//正确的修改方法：
	ander.name = "灰太狼"
	map0[1] = ander
}

type User struct {
	name string
	age  int
}
